{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Quick start"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For convenience, let's begin by enabling [automatic reloading of modules](https://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html?highlight=autoreload) when they change."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Import Qiskit Metal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import qiskit_metal as metal\n",
    "from qiskit_metal import designs, draw\n",
    "from qiskit_metal import MetalGUI, Dict, open_docs\n",
    "\n",
    "%metal_heading Welcome to Qiskit Metal!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## My first Quantum Design (QDesign)\n",
    "\n",
    "A Quantum Design (``QDesign``) can be selected from the design library `qiskit_metal.designs`. All designs are children of the `QDesign` base class, which defines the basic funcationality of a QDesign. \n",
    "\n",
    "We will start with the simple planar QDesign.\n",
    "\n",
    "```python \n",
    "design = designs.DesignPlanar()\n",
    "```\n",
    "\n",
    "##### Interactivly view, edit, and simulate QDesign: Metal GUI\n",
    "\n",
    "To launch the qiskit metal GUI,use the method `MetalGUI`.\n",
    "```python \n",
    "gui = MetalGUI(design)\n",
    "```\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design = designs.DesignPlanar()\n",
    "gui = MetalGUI(design)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_heading Hello Quantum World!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## My First Quantum Component (QComponent)\n",
    "### A transmon qubit\n",
    "We can create a ready-made and optimized transmon qubit form the QLibrary of components.\n",
    "Qubit qcomponents are stored in the library `qiskit_metal.qlibrary.qubits`. The file that contains the transmon pocket is called `transmon_pocket`,\n",
    "and the `QComponent` class inside it is `TransmonPocket`.\n",
    "\n",
    "* Let's create a new qubit by creating an object of this class. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Select a QComponent to create (The QComponent is a python class named `TransmonPocket`)\n",
    "from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket\n",
    "\n",
    "# Create a new qcomponent object with name 'Q1' \n",
    "q1 = TransmonPocket(design, 'Q1')\n",
    "gui.rebuild()  # rebuild the design and plot "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# save screenshot\n",
    "gui.edit_component('Q1')\n",
    "gui.autoscale()\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's see what the Q1 object looks like"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "q1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Parsed view of options"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### What are the default options?\n",
    "The QComponent comes with some default options. The options are used in the `make` function of the qcomponent to create the QGeometry you see in the plot above. \n",
    "* Options are parsed by Qiskit Metal. \n",
    "* You can change them from the gui or the script api. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_print How do I edit options?  API or GUI"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can use the gui to create, edit, plot, modify, quantum components.\n",
    "Equivalently, you can also do everything form the python API. \n",
    "The GUI is just calling the API for you."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Change options\n",
    "q1.options.pos_x = '0.5 mm'\n",
    "q1.options.pos_y = '0.25 mm'\n",
    "q1.options.pad_height = '225 um'\n",
    "q1.options.pad_width  = '250 um'\n",
    "q1.options.pad_gap    = '50 um'\n",
    "\n",
    "# Update the geoemtry, since we changed the options\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.autoscale()\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Where are the QComponents stored?\n",
    "They are stored in `design.components`. It can be accessd as a dictionary (`design.components['Q1']`) or object (`design.components.Q1`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "q1 = design.components['Q1']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_print Where are the default options? "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A QComponent is created with default options.\n",
    "To find out what these are use `QComponentClass.get_template_options(design)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "TransmonPocket.get_template_options(design)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_print How do I change the default options? "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now lets change the default options we will use to create the transmon"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# THIS ISN'T CHANGING THE DEFAULT OPTIONS - NEEDS UPDATE\n",
    "q1.options.pos_x = '0.5 mm'\n",
    "q1.options.pos_y = '250 um'\n",
    "\n",
    "# Rebubild for changes to propagate\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_print How do I work with units? <br><br> (parse options and values) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Parsing strings into floats"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Use the `design.parse_value` or `QComponent.parse_value` (such as `q1.parse_value`). The two functions serve the same purpose. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('Design default units for length: ', design.get_units())\n",
    "print('\\nExample 250 micron parsed to design units:', design.parse_value('0.250 um'),  design.get_units())\n",
    "\n",
    "dictionary = {'key_in_cm': '1.2 cm', 'key_in_microns': '50 um'}\n",
    "print('\\nExample parse dict:', design.parse_value(dictionary))\n",
    "\n",
    "a_list = ['1m', '1mm', '1um', '1 nm']\n",
    "print('\\nExample parse list:', design.parse_value(a_list))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Some basic arithmetic and parsing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.parse_value('2 * 2um')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.parse_value('2um + 5um')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.qgeometry.tables['junction']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Advanced: parse into arrays, list, etc.  \n",
    "Can use python syntax inside options. Parse uses pythonic `ast_eval`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#### List \n",
    "print('* '*10+' LIST '+'* '*10,'\\n')\n",
    "str_in = \"[1,2,3,'10um']\"\n",
    "out = design.parse_value(str_in)\n",
    "print(f'Parsed output:\\n {str_in}  ->  {out} \\n Out type: {type(out)}\\n')\n",
    "\n",
    "str_in = \"['2*2um', '2um + 5um']\"\n",
    "out = design.parse_value(str_in)\n",
    "print(f'Parsed output:\\n {str_in}  ->  {out} \\n Out type: {type(out)}\\n')\n",
    "\n",
    "#### Dict\n",
    "print('* '*10+' DICT '+'* '*10,'\\n')\n",
    "\n",
    "str_in = \"{'key1': '100um', 'key2': '1m'}\"\n",
    "out = design.parse_value(str_in)\n",
    "print(f'Parsed output:\\n {str_in}  ->  {out} \\n Out type: {type(out)}\\n')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How do I overwrite QComponents? "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To enable component overwrite of components with the same name, use the following cell "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.overwrite_enabled = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_heading Quantum pins: QPins!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### QPins: The dynamic way to connect qcomponents \n",
    "\n",
    "The component designer can define pins. Pins can be used to link components together. For examaple, two transmon can each have a pin. The two pins can be connectoed by CPWs, as we will show below. \n",
    "\n",
    "First, let us add pins to the transmon. \n",
    "We will add 4 pins called `a`, `b`, `c`, and `d`. \n",
    "Each pin will be at a differnet location (corner of the transmon), defined by the options `loc_W` and `loc_H`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket\n",
    "\n",
    "design.delete_all_components()\n",
    "\n",
    "options = dict(\n",
    "    pad_width = '425 um', \n",
    "    pocket_height = '650um',\n",
    "    connection_pads=dict(  # pin connecotrs\n",
    "        a = dict(loc_W=+1,loc_H=+1), \n",
    "        b = dict(loc_W=-1,loc_H=+1, pad_height='30um'),\n",
    "        c = dict(loc_W=+1,loc_H=-1, pad_width='200um'),\n",
    "        d = dict(loc_W=-1,loc_H=-1, pad_height='50um')\n",
    "    )\n",
    ")\n",
    "\n",
    "q1 = TransmonPocket(design, 'Q1', options = dict(pos_x='+0.5mm', pos_y='+0.5mm', **options))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Take a screenshot with the component highlighted and the pins shown\n",
    "gui.rebuild()\n",
    "gui.autoscale()\n",
    "gui.edit_component('Q1')\n",
    "gui.zoom_on_components(['Q1'])\n",
    "gui.highlight_components(['Q1'])\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To access a pin"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "q1.pins.a\n",
    "q1.pins['a']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### How do I edit the component source code and see changes immidietly? \n",
    "If you have selected a QComponent, you can call the button that says edit source in the gui. \n",
    "Once selected, you could also call the same function from the code."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.edit_component('Q1')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This will pop open a new source editor window, you can change the source on the fly. \n",
    "* Make sure you press the `Rebuild component` button in the source editor when you are ready to save and make your changes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_heading My first quantum chip"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Creating a whole chip of qubit with connectors "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's now create a a whole chip. In the following, you will pass options to create 4 transmons qubits in a ring.\n",
    "First let us clear all qcomponents in the design. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.delete_all_components() \n",
    "gui.rebuild() # refresh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket\n",
    "\n",
    "# Allow running the same cell here multiple times to overwrite changes\n",
    "design.overwrite_enabled = True\n",
    "\n",
    "## Custom options for all the transmons\n",
    "options = dict(\n",
    "    # Some options we want to modify from the deafults\n",
    "    # (see below for defaults)\n",
    "    pad_width = '425 um', \n",
    "    pocket_height = '650um',\n",
    "    # Adding 4 connectors (see below for defaults)\n",
    "    connection_pads=dict( \n",
    "        a = dict(loc_W=+1,loc_H=+1), \n",
    "        b = dict(loc_W=-1,loc_H=+1, pad_height='30um'),\n",
    "        c = dict(loc_W=+1,loc_H=-1, pad_width='200um'),\n",
    "        d = dict(loc_W=-1,loc_H=-1, pad_height='50um')\n",
    "    )\n",
    ")\n",
    "\n",
    "## Create 4 transmons\n",
    "\n",
    "q1 = TransmonPocket(design, 'Q1', options = dict(\n",
    "    pos_x='+2.55mm', pos_y='+0.0mm', **options))\n",
    "q2 = TransmonPocket(design, 'Q2', options = dict(\n",
    "    pos_x='+0.0mm', pos_y='-0.9mm', orientation = '90', **options))\n",
    "q3 = TransmonPocket(design, 'Q3', options = dict(\n",
    "    pos_x='-2.55mm', pos_y='+0.0mm', **options))\n",
    "q4 = TransmonPocket(design, 'Q4', options = dict(\n",
    "    pos_x='+0.0mm', pos_y='+0.9mm', orientation = '90', **options))\n",
    "\n",
    "## Rebuild the design\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.toggle_docks(True)\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_heading Connecting QPins with coplanar waveguides (CPWs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's import the basic cpw QComponent from the QLibrary. It is a class called `RouteMeander`.\n",
    "We can see its default options using `RouteMeander.get_template_options(design)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.tlines.meandered import RouteMeander\n",
    "RouteMeander.get_template_options(design)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now modify the options and connect all four qubits. Since this is repetative, you can define a function to wrap up the repetatvie steps. Here we will call this `connect`. This function creates a `RouteMeander` QComponent class."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = Dict(\n",
    "    meander=Dict(\n",
    "        lead_start='0.1mm',\n",
    "        lead_end='0.1mm',\n",
    "        asymmetry='0 um')\n",
    ")\n",
    "\n",
    "\n",
    "def connect(component_name: str, component1: str, pin1: str, component2: str, pin2: str,\n",
    "            length: str,\n",
    "            asymmetry='0 um', flip=False):\n",
    "    \"\"\"Connect two pins with a CPW.\"\"\"\n",
    "    myoptions = Dict(\n",
    "        pin_inputs=Dict(\n",
    "            start_pin=Dict(\n",
    "                component=component1,\n",
    "                pin=pin1),\n",
    "            end_pin=Dict(\n",
    "                component=component2,\n",
    "                pin=pin2)),\n",
    "        lead=Dict(\n",
    "            start_straight='0.13mm'\n",
    "        ),\n",
    "        total_length=length,\n",
    "    fillet = '90um')\n",
    "    myoptions.update(options)\n",
    "    myoptions.meander.asymmetry = asymmetry\n",
    "    myoptions.meander.lead_direction_inverted = 'true' if flip else 'false'\n",
    "    return RouteMeander(design, component_name, myoptions)\n",
    "\n",
    "\n",
    "asym = 150\n",
    "cpw1 = connect('cpw1', 'Q1', 'd', 'Q2', 'c', '6.0 mm', f'+{asym}um')\n",
    "cpw2 = connect('cpw2', 'Q3', 'c', 'Q2', 'a', '6.1 mm', f'-{asym}um', flip=True)\n",
    "cpw3 = connect('cpw3', 'Q3', 'a', 'Q4', 'b', '6.0 mm', f'+{asym}um')\n",
    "cpw4 = connect('cpw4', 'Q1', 'b', 'Q4', 'd', '6.1 mm', f'-{asym}um', flip=True)\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.toggle_docks(True)\n",
    "gui.highlight_components(['Q1','Q2','Q3','Q4','cpw1','cpw2','cpw3','cpw4'])\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.components.keys()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can access the created CPW from the design too."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.components.cpw2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see all the pins"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_heading Variables in options"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Variables "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The design can have variables, which can be used in the component options."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.variables.cpw_width = '10um'\n",
    "design.variables.cpw_gap = '6um'\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For example, we can all qubit pads using the variables.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cpw1.options.lead.end_straight = '100um'\n",
    "cpw2.options.lead.end_straight = '100um'\n",
    "cpw3.options.lead.end_straight = '100um'\n",
    "cpw4.options.lead.end_straight = '100um'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set variables in the design\n",
    "design.variables.pad_width = '450 um'\n",
    "design.variables.cpw_width = '25 um'\n",
    "design.variables.cpw_gap = '12 um'\n",
    "\n",
    "# Assign variables to component options\n",
    "q1.options.pad_width = 'pad_width'\n",
    "q2.options.pad_width = 'pad_width'\n",
    "q3.options.pad_width = 'pad_width'\n",
    "q4.options.pad_width = 'pad_width'\n",
    "\n",
    "# Rebuild all compoinent and refresh the gui \n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_heading Render to GDS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gds = design.renderers.gds\n",
    "gds.options.path_filename"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gds.options.path_filename = '../resources/Fake_Junctions.GDS'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "q1.options"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## gds.options.path_filename"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Need to give the correct path and filename that has gds formatted cells.\n",
    "An example is located in the repositary under resources directory.\n",
    "The cells are \"junctions\" that would be placed inside qubits.  Fake_Junctions has \n",
    "three cells named: \"Fake_Junction_01\", \"Fake_Junction_02\", \"my_other_junction\".  \n",
    "\n",
    "Example:  When creating transmon the default_option for gds_cell_name is \"my_other_junction\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gds.options.path_filename = \"../resources/Fake_Junctions.GDS\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design.renderers.gds.export_to_gds(\"awesome_design.gds\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_heading More QComponents"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Basic and crazy shapes. \n",
    "\n",
    "See their source code to see how to get started on a few simple examples."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.sample_shapes.n_square_spiral import NSquareSpiral\n",
    "# print(NSquareSpiral.get_template_options(design))\n",
    "ops = {\n",
    "    'n': '10',\n",
    "    'width': '10um',\n",
    "    'radius': '100um',\n",
    "    'gap': '22um',\n",
    "    'pos_x': '0.65mm',\n",
    "    'pos_y': '2.2mm',\n",
    "    'orientation': '0',\n",
    "    'subtract': 'False'}\n",
    "NSquareSpiral(design, 'spiral', ops)\n",
    "NSquareSpiral(design, 'spiral_cut', {**ops, **dict(subtract=True, width='22um', gap='10um')})\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To see source, try ``??NSquareSpiral``. Go to the actual source file and edit it, copy it, or edit it in the GUI using the `Edit Source` button."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.tlines.straight_path import RouteStraight\n",
    "# CpwStraightLine.get_template_options(design)\n",
    "myoptions = Dict(\n",
    "        pin_inputs=Dict(\n",
    "            start_pin=Dict(\n",
    "                component='Q4',\n",
    "                pin='c'),\n",
    "            end_pin=Dict(\n",
    "                component='spiral',\n",
    "                pin='spiralPin'))\n",
    "        )\n",
    "\n",
    "\n",
    "RouteStraight(design, 'cpw_s1', myoptions);\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "qcomponents = ['spiral', 'cpw_s1']\n",
    "gui.highlight_components(qcomponents)\n",
    "gui.zoom_on_components(qcomponents)\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "####  NGon"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.sample_shapes.n_gon import NGon\n",
    "# display(NGon.get_template_options(design))\n",
    "ops = {\n",
    "    'n': '5',\n",
    "    'radius': '250um',\n",
    "    'pos_x': '-0.85mm',\n",
    "    'pos_y': '2.0mm',\n",
    "    'orientation': '15',\n",
    "    'subtract': 'False',\n",
    "    'helper': 'False',\n",
    "    'chip': 'main',\n",
    "    'layer': '1'}\n",
    "NGon(design, 'ngon', ops)\n",
    "NGon(design, 'ngon_negative', {**ops, **dict(subtract=True, radius='350um')})\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.zoom_on_components(['ngon_negative'])\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.sample_shapes.circle_raster import CircleRaster\n",
    "display(CircleRaster.get_template_options(design))\n",
    "\n",
    "ops = { 'radius': '300um',\n",
    "        'pos_x': '-1.5mm',\n",
    "        'pos_y': '2mm',\n",
    "        'resolution': '16',\n",
    "        'cap_style': 'round',\n",
    "        'subtract': 'False',\n",
    "        'helper': 'False',\n",
    "        'chip': 'main',\n",
    "        'layer': '1'}\n",
    "CircleRaster(design, 'CircleRaster', ops)\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.zoom_on_components(['CircleRaster'])\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.sample_shapes.rectangle_hollow import RectangleHollow\n",
    "display(RectangleHollow.get_template_options(design))\n",
    "\n",
    "ops = { 'width': '500um',\n",
    "        'height': '300um',\n",
    "        'pos_x': '-2.3mm',\n",
    "        'pos_y': '2mm',\n",
    "        'orientation': '0',\n",
    "        'subtract': 'False',\n",
    "        'helper': 'False',\n",
    "        'chip': 'main',\n",
    "        'layer': '1',\n",
    "        'inner': {  'width': '250um',\n",
    "                    'height': '100um',\n",
    "                    'offset_x': '40um',\n",
    "                    'offset_y': '-20um',\n",
    "                    'orientation': '15'}}\n",
    "RectangleHollow(design, 'RectangleHollow', ops)\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.zoom_on_components(['RectangleHollow'])\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.autoscale()\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_heading The geometry of QComponent: QGeometry"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Geometric boundary of a qcomponent?\n",
    "Return the boundry box of the geometry, for example: `q1.qgeometry_bounds()`.  \n",
    "The function returns a tuple containing (minx, miny, maxx, maxy) bound values\n",
    "for the bounds of the component as a whole."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for name, qcomponent in design.components.items():\n",
    "    print(f\"{name:10s} : {qcomponent.qgeometry_bounds()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### What is QGeometry? "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can get all the QGeometry of a QComponent. There are several kinds, such as `path` and `poly`. Let us look at all the polygons used to create qubit `q1`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "q1.qgeometry_table('poly')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Paths are lines. These can have a width."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "q1.qgeometry_table('path')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Junction table holds information about Quantum juctions. Placement is defined by LineString and width. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "q1.qgeometry_table('junction')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%metal_heading Qiskit Metal Version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "metal.about();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Can close Metal GUI from both notebook and GUI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# gui.main_window.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
